package com.github.md11235.ideaproofofwork.util

import com.github.md11235.ideaproofofwork.cfiletracker.CFileTrackerUI
import com.github.md11235.ideaproofofwork.entity.ActionType
import com.github.md11235.ideaproofofwork.entity.FileChangeEvent
import com.google.gson.GsonBuilder
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.editor.event.EditorFactoryEvent
import com.intellij.openapi.editor.event.EditorFactoryListener
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ContentIterator
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.startup.ProjectActivity
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.openapi.vfs.VirtualFile
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardOpenOption
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Base64
import java.util.zip.GZIPOutputStream


    private val log = Logger.getInstance("CSourceFile::module")

    private val gson =  GsonBuilder().disableHtmlEscaping().create()

    fun encodeFileToGzipBase64(virtualFile: VirtualFile): String {
        virtualFile.inputStream.use { input ->
            ByteArrayOutputStream().use { byteOutputStream ->
                GZIPOutputStream(byteOutputStream).use { gzipStream ->
                    input.copyTo(gzipStream)
                }
                return Base64.getEncoder().encodeToString(byteOutputStream.toByteArray())
            }
        }
    }

    fun getNewFilePath(virtualFile: VirtualFile, newFilename: String): String? {
        return virtualFile.parent?.path?.let { parentPath ->
            File(parentPath, newFilename).absolutePath
        }
    }

    fun snapshotCSourceFiles(project: Project) {
        val projectFileIndex = ProjectFileIndex.getInstance(project)

        projectFileIndex.iterateContent(object : ContentIterator {
            override fun processFile(fileOrDir: VirtualFile): Boolean {
                if (!fileOrDir.isDirectory) {
                    // Process the file here
                    if (fileOrDir.extension == "c") {
                        println("Taking a snapshot: ${fileOrDir.path}")
                        val snapshotEvent = FileChangeEvent(
                            System.currentTimeMillis(),
                            ActionType.SNAPSHOT, 0, fileOrDir.path,
                            encodeFileToGzipBase64(fileOrDir),
                            ""
                        )

                        val msg = gson.toJson(snapshotEvent)

                        val logFile = getNewFilePath(fileOrDir, "${fileOrDir.name}.steps.txt")
                        CFileTrackerUI.addEvent(msg)
                        appendToLogFile(Path.of(logFile.toString()), msg)
                        // given fileOrDir.path, read its content, gzip it and base64 encode into a string

                    }
                }
                return true // Continue iteration
            }
        })
    }

fun convertToJson(event: FileChangeEvent): String {
    return gson.toJson(event)
}

fun appendToLogFile(path: Path, message: String) {
    try {
        Files.writeString(
            path,
            message + System.lineSeparator(),
            StandardOpenOption.CREATE,
            StandardOpenOption.APPEND
        )
    } catch (e: Exception) {
        log.warn("Failed to write log ${path}: ${e.message}")
    }
}
